import Node from '../core/Node';
import Layer from '../core/Layer';

class KBar extends Node {
    static BAR_TYPE = {
        FILL: 1,
        STROKE: 2,
    }

    constructor(canvas, style, data) {
        super(canvas, style);
        this.open = data.oopen;
        this.high = data.high;
        this.low = data.low;
        this.close = data.close;
        this.open = data.open;
        this.datetime = data.datetime;
        this.barWidth = style.barWidth; // 蜡烛宽度
        this.delta = style.delta;
        this.baseLine = style.baseLine || 0; // 数值基线
        this.type = style.type || KBar.BAR_TYPE.FILL;
    }

    draw(painter) {
        // 计算矩形部分的高 |开盘-收盘| * 单位数值所占用的像素
        let barHeight = Math.round(Math.abs(this.close - this.open) * this.delta);
        // 防止开盘价与收盘价相等，高度为0，如十字线，默认最小2像素
        barHeight = barHeight > 2 ? barHeight : 3;
        painter.strokeStyle = this.color;
        painter.strokeWidth = '2px';
        painter.lineWidth = 1.5;
        painter.fillStyle = this.color;
        let top = Math.max(this.open, this.close);  // 矩形上边界值
        let bottom = Math.min(this.open, this.close);  // 矩形下边界值
        if (this.type === KBar.BAR_TYPE.STROKE) {
            // 当前类型为线框
            // 绘制上部分线条开始
            painter.beginPath();
            // 移到最高点
            painter.moveTo(Math.round(this.left + this.barWidth / 2), Math.round(this.bottom - (this.high - this.baseLine) * this.delta));
            // 移动到矩形上边界
            painter.lineTo(Math.round(this.left + this.barWidth / 2), Math.round(this.left - (top - this.baseLine) * this.delta));
            painter.closePath();
            painter.stroke();
            // 上部分线条绘制结束
            // 绘制下部分线条开始
            painter.beginPath();
            // 移动到最低价位置
            painter.moveTo(Math.round(this.left + this.barWidth / 2), Math.round(this.bottom - (this.low - this.baseLine) * this.delta));
            // 移动到矩形下边界
            painter.lineTo(Math.round(this.left + this.barWidth / 2), Math.round(this.bottom - (bottom - this.baseLine) * this.delta));
            painter.closePath();
            painter.stroke();
            // 下部分线条结束
            // 绘制矩形部分
            painter.strokeRect(
                this.left + Math.round(0.15 * this.barWidth),
                this.bottom - Math.round((top - this.baseLine) * this.delta),
                Math.round(this.barWidth * 0.7),
                barHeight
            );
            // 绘制矩形结束
        } else {
            // 绘制最高最低价线型
            painter.beginPath();
            // 最高价
            painter.moveTo(Math.round(this.left + this.barWidth / 2), Math.round(this.bottom - (this.high - this.baseLine) * this.delta));
            // 最低价
            painter.lineTo(Math.round(this.left + this.barWidth / 2), Math.round(this.bottom - (this.low - this.baseLine) * this.delta));
            painter.closePath();
            painter.stroke();
            // 线型绘制结束
            // 绘制矩形部分
            painter.fillRect(
                this.left + Math.round(0.15 * this.barWidth),
                this.bottom - Math.round((top - this.baseLine) * this.delta),
                Math.round(this.barWidth * 0.7),
                barHeight
            );
        }
    }
    containsPoint(point) {
        return false;
    }
}

export default class extends Layer {
    constructor(canvas, style, data = []) {
        super(canvas, style);
        this.data = data || [];
        this.positiveColor = style.positiveColor || '#EE1100';
        this.negativeColor = style.negativeColor || '#00C000';
        this.positiveType = style.positiveType || KBar.BAR_TYPE.FILL;
        this.negativeType = style.negativeType || KBar.BAR_TYPE.FILL;
        this.barNum = style.barNum || 30;
        this.locked = style.locked || false;
        this.xShift = style.xShift || 0;
        this.indicatorLayers = [];
    }

    getMaxMin(painter) {
        if (this.data.length === 0) {
            return {
                max: 0,
                min: 0,
            };
        }
        const barWidth = this.width / this.barNum;
        const kleft = Math.floor(this.xShift / barWidth);
        let barEnd = this.data.length - 1;
        let barStart = this.data.length - this.barNum;
        if (kleft >= 0 && this.data.length > kleft + this.barNum) {
            // 向右移动数量与显示数量小于数据量，结束索引等于数据量-偏移量
            barEnd = this.data.length - 1 - kleft;
            barStart = barEnd - this.barNum;
        } else if (kleft >= 0) {
            barEnd = this.barNum;
            barStart = 0;
        } else {
            // 向左移动
            barEnd = this.data.length - 1;
            barStart = barEnd - this.barNum - kleft;
        }
        this.barStart = barStart;
        this.barEnd = barEnd;
        let max = this.data[barStart].high;
        let min = this.data[barStart].low;
        for (let i = barStart; i <= barEnd; i++) {
            if (this.data[i].high > max) {
                max = this.data[i].high;
            }
            if (this.data[i].low < min) {
                min = this.data[i].low;
            }
        }
        if (this.indicatorLayers.length > 0) {
            for (let i = 0; i < this.indicatorLayers.length; i++) {
                const indicatorLayer = this.indicatorLayers[i];
                indicatorLayer.data = this.data;
                indicatorLayer.dataStart = barStart;
                indicatorLayer.dataEnd = barEnd;
                indicatorLayer.caculate(painter);
                if (max < indicatorLayer.max) {
                    max = indicatorLayer.max;
                }
                if (min > indicatorLayer.min) {
                    min = indicatorLayer.min;
                }
            }
        }
        this.max = max;
        this.min = min;
        return {
            max,
            min,
        };
    }

    build(painter) {
        if (this.data.length === 0) {
            return;
        }
        this.childs.splice(0, this.childs.length);
        const barWidth = this.width / this.barNum;
        const { max, min } = this.getMaxMin();
        const { barStart, barEnd } = this;
        let yDelta = this.height / (max - min);
        for (let i = barStart; i <= barEnd; i++) {
            const isPositive = Number(this.data[i].close) > Number(this.data[i].open);
            const color = isPositive ? this.positiveColor : this.negativeColor;
            const type = isPositive ? this.positiveType : this.negativeType;
            const kbar = new KBar(this.canvas, {
                barWidth: barWidth,
                delta: yDelta,
                baseLine: min,
                color,
                type,
                position: 'absolute',
                left: (i - barStart) * barWidth,
                bottom: 0,
            }, this.data[i]);
            this.addChild(kbar);
        }
        if (this.indicatorLayers.length > 0) {
            for (let i = 0; i < this.indicatorLayers.length; i++) {
                const indicatorLayer = this.indicatorLayers[i];
                if (indicatorLayer.render) {
                    indicatorLayer.render(
                        {
                            max,
                            min,
                            xStep: barWidth,
                            yStep: yDelta,
                            start: barStart,
                            end: barEnd,
                        }
                    );
                }
                indicatorLayer.width = '100%';
                indicatorLayer.height = '100%';
                this.addChild(indicatorLayer);
            }
        }
        console.log('k line bar===>', this);
        this.onBuilded && this.onBuilded(this, {
            max,
            min,
            xStep: barWidth,
            yStep: yDelta,
            start: barStart,
            end: barEnd,
        });
    }
}
